package cn.itsource.basic.service.impl;

import cn.itsource.basic.dto.CodeDto;
import cn.itsource.basic.dto.EmaDto;
import cn.itsource.basic.exception.BusinessException;
import cn.itsource.basic.service.IVerifyCodeService;
import cn.itsource.basic.util.StrUtils;
import cn.itsource.basic.util.VerifyCodeUtils;
import cn.itsource.user.domain.User;
import cn.itsource.user.mapper.UserMapper;
import cn.itsource.user.mapper.WxuserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private WxuserMapper wxuserMapper;
    //获取图形验证码
    @Override
    public String imageVerifyCode(String key) {
        //调用StrUtils工具类生成图形验证码
        String code = StrUtils.getComplexRandomString(4);

        //将传入的参数key和图形验证码保存到redis去  设置5分钟
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);

        return VerifyCodeUtils.verifyCode(115,40,code);
    }


    //获取手机验证码
    @Override
    public void phoneVerifyCode(CodeDto codeDto) {
        //获取手机号码
        String phone = codeDto.getPhone();
        //获取图形验证码
        String imageCode = codeDto.getImageCode();
        //获取图形验证码的key
        String key = codeDto.getImageCodeKey();

        //1.首先进行空值校验
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不可为空");
        }
        if(StringUtils.isEmpty(imageCode)){
            throw new BusinessException("请输入图形验证码");
        }
        if(StringUtils.isEmpty(key)){
            throw new BusinessException("重新获取图形验证码");
        }
        //2.校验手机号是否已经注册过
        User user = userMapper.findByPhone(phone);
        if(user != null){
            throw new BusinessException("该手机已经注册，请直接登录!");
        }

        //3.校验图形验证码是否过期
        //拿到数据库里的图形验证码对象
        Object imgObj  = redisTemplate.opsForValue().get(key);
        if(imgObj  == null){
            throw new BusinessException("图片验证码过期，请重新输入!");
        }
        //校验图形验证码是否错误
        if(!imgObj.toString().equalsIgnoreCase(imageCode)){
            throw new BusinessException("图片验证码输入错误，请重新输入");
        }
        //4.生成手机验证码
        // 直接从redis获取手机验证码 key:[业务键:手机号]
        Object codeObj = redisTemplate.opsForValue().get("register:" + phone);
        String code =null;
        if(codeObj == null){//表示过期
            //重新获取验证码
            code= StrUtils.getRandomString(4);
            //有验证码 判断是否过期
        }else {
            //获取当前系统时间戳
            Long nowTime  = System.currentTimeMillis();
            //最开始发送第一次验证码的时间
            String oldTimeTemp = codeObj.toString().split(":")[1];
            //将其转成Long类型
            Long oldTime = Long.parseLong(oldTimeTemp);
            //判断现在的时间减去老的时间是否小于一分钟
            if((nowTime-oldTime)<1*60*1000){
                //如果是表示在一分钟内重复点击获取 虽然前端做了点击获取之后 获取按钮不可用
                //但是为了防止在一分钟之内刷新页面再点击获取 需要在后端做判断来防止
                throw new BusinessException("操作频繁请稍后重试");
            }else {
                code = codeObj.toString().split(":")[0];
            }

        }
        //5.手机验证码保存到redis
        redisTemplate.opsForValue().set("register:"+phone,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //6.调用工具类发送短信
        //SmsUtils.sendSms(phone,"你的验证码是:"+code+"请在三分钟内填写验证码");
        System.out.println("你的验证码是:"+code+",请在三分钟内填写验证码");

    }

    //获取邮箱验证码
    @Override
    public void emailCode(EmaDto emaDto) {
        //获取用户输入的邮箱
        String email = emaDto.getEmail();
        //获取图形验证码
        String emailImageCode = emaDto.getEmailImageCode();
        //获取图形验证码的key
        String key = emaDto.getEmailImageCodeKey();

        //1.首先进行空值校验
        if(StringUtils.isEmpty(email)||StringUtils.isEmpty(emailImageCode)||StringUtils.isEmpty(key)){
            throw new BusinessException("信息不能为空");
        }

        //2.校验手机号是否已经注册过
        User user = userMapper.findByEmail(email);
        if(user != null){
            throw new BusinessException("该邮箱已经注册，请直接登录!");
        }

        //3.校验图形验证码是否过期
        //拿到数据库里的图形验证码对象
        Object emoObj  = redisTemplate.opsForValue().get(key);
        if(emoObj  == null){
            throw new BusinessException("图片验证码过期，请重新输入!");
        }
        //校验图形验证码是否错误
        if(!emoObj.toString().equalsIgnoreCase(emailImageCode)){
            throw new BusinessException("图片验证码输入错误，请重新输入");
        }
        //4.生成手机验证码
        // 直接从redis获取手机验证码 key:[业务键:手机号]
        Object codeObj = redisTemplate.opsForValue().get("register:" + email);
        String code =null;
        if(codeObj == null){//表示没有过期
            //重新获取验证码
            code= StrUtils.getRandomString(4);
            //有验证码 判断是否过期
        }else {
            //获取当前系统时间戳
            Long nowTime  = System.currentTimeMillis();
            //最开始发送第一次验证码的时间
            String oldTimeTemp = codeObj.toString().split(":")[1];
            //将其转成Long类型
            Long oldTime = Long.parseLong(oldTimeTemp);
            //判断现在的时间减去老的时间是否小于一分钟
            if((nowTime-oldTime)<1*60*1000){
                //如果是表示在一分钟内重复点击获取 虽然前端做了点击获取之后 获取按钮不可用
                //但是为了防止在一分钟之内刷新页面再点击获取 需要在后端做判断来防止
                throw new BusinessException("操作频繁请稍后重试");
            }else {
                code = codeObj.toString().split(":")[0];
            }

        }
        //5.手机验证码保存到redis
        redisTemplate.opsForValue().set("register:"+email,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //6.发送邮件
        //简单邮件消息 只能是纯文本
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        //设置发送人
        mailMessage.setFrom("1069494754@qq.com");
        //邮件主题
        mailMessage.setSubject("爱的邮件信息");
        //邮件内容：普通文件无法解析html标签
        mailMessage.setText("你的验证码是："+code+"请在三分钟内使用");
        //收件人
        mailMessage.setTo("1026178117@qq.com");
        //发送邮件  通过java邮件的发送者去发送一个简单的邮件信息
        mailSender.send(mailMessage);

    }


    //绑定
    @Override
    public void binderVerifyCode(CodeDto codeDto) {
        //获取手机号码
        String phone = codeDto.getPhone();

        //1.首先进行空值校验
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不可为空");
        }

        //2.校验手机号是否已经注册过
        User user = userMapper.findByWxUserPhone(phone);

        if(user != null){
            throw new BusinessException("该号码已经绑定过微信，请直接登录!");
        }

        //4.生成手机验证码
        // 直接从redis获取手机验证码 key:[业务键:手机号]
        Object phoneCode = redisTemplate.opsForValue().get("binder:" + phone);
        String code =null;
        if(phoneCode == null){//表示没有过期
            //重新获取验证码
            code= StrUtils.getRandomString(4);
            //有验证码 判断是否过期
        }else {
            //获取当前系统时间戳
            Long nowTime  = System.currentTimeMillis();
            //最开始发送第一次验证码的时间
            String oldTimeTemp = phoneCode.toString().split(":")[1];
            //将其转成Long类型
            Long oldTime = Long.parseLong(oldTimeTemp);
            //判断现在的时间减去老的时间是否小于一分钟
            if((nowTime-oldTime)<1*60*1000){
                //如果是表示在一分钟内重复点击获取 虽然前端做了点击获取之后 获取按钮不可用
                //但是为了防止在一分钟之内刷新页面再点击获取 需要在后端做判断来防止
                throw new BusinessException("操作频繁请稍后重试");
            }else {
                code = phoneCode.toString().split(":")[0];
            }

        }
        //5.手机验证码保存到redis
        redisTemplate.opsForValue().set("binder:"+phone,code+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

        //6.调用工具类发送短信
        //SmsUtils.sendSms(phone,"你的验证码是:"+code+"请在三分钟内填写验证码");
        System.out.println("你的验证码是:"+code+",请在三分钟内填写验证码");

    }
}
